/**
 * 
 */
package org.neptune.service.service.impl;

import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.neptune.api.entity.CaptchaCacheBean;
import org.neptune.api.request.LoginRequest;
import org.neptune.common.constant.CharacterConstant;
import org.neptune.common.constant.NeptuneConstant;
import org.neptune.common.util.RandomUtils;
import org.neptune.common.util.UnZipFileUtil;
import org.neptune.common.util.VerifyImageUtil;
import org.neptune.service.config.NeptuneConfig;
import org.neptune.service.redis.RedisRepository;
import org.neptune.service.redis.RedissonUtil;
import org.neptune.service.service.CaptchaService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.base.Splitter;

/**
 * @author dell
 */
@Service
public class CaptchaServiceImpl implements CaptchaService {

	private static final Logger LOGGER = LoggerFactory.getLogger(CaptchaServiceImpl.class);

	private static final String IMG_PATH = "/targetImgs";

	private static final String TEMP_IMG_PATH = "/templateImgs";

	private static final String BOOT_PATH = "/BOOT-INF/classes";

	@Autowired
	private NeptuneConfig neptuneConfig;

	@Autowired
	private RedisRepository redisRepository;

	@PostConstruct
	void init() throws IOException {
		String rootPath = getClass().getResource("").getPath();
		if (rootPath.indexOf(CharacterConstant.EXCLAMATION_MARK_EN) > 0){
			LOGGER.info("########## start unzip jar file #########");
			List<String> paths = Splitter.on(CharacterConstant.EXCLAMATION_MARK_EN)
					.splitToList(rootPath);
			// 兼容掉文件路径多file:前缀
			String sourceFile = StringUtils.replace(paths.get(0), "file:", "");

			UnZipFileUtil.uncompressZip(sourceFile);

			String fileName = sourceFile.substring(0, sourceFile.lastIndexOf("."));

			String imagePath = fileName + BOOT_PATH + IMG_PATH;
			String templatePath = fileName + BOOT_PATH + TEMP_IMG_PATH;
			UnZipFileUtil.createFolder(neptuneConfig.captchaImgPath + IMG_PATH);
			UnZipFileUtil.createFolder(neptuneConfig.captchaImgPath + TEMP_IMG_PATH);
			UnZipFileUtil.copyToTargetFolder(imagePath, neptuneConfig.captchaImgPath + IMG_PATH);
			UnZipFileUtil.copyToTargetFolder(templatePath,
					neptuneConfig.captchaImgPath + TEMP_IMG_PATH);
			LOGGER.info("########## end unzip jar file #########");
		}
	}

	@Override
	public Map<String, Object> getImageVerifyCode() throws Exception {
		// 读取图库目录
		// 兼容开发和部署
		File imgCatalog = new File(getClass().getResource(IMG_PATH).getPath());
		File[] files = imgCatalog.listFiles();
		if (files == null){
			imgCatalog = new File(neptuneConfig.captchaImgPath + IMG_PATH);
			files = imgCatalog.listFiles();
		}
		File tempImgCatalog = new File(getClass().getResource(TEMP_IMG_PATH).getPath());
		File[] tempFiles = tempImgCatalog.listFiles();
		if (tempFiles == null){
			tempImgCatalog = new File(neptuneConfig.captchaImgPath + TEMP_IMG_PATH);
			tempFiles = tempImgCatalog.listFiles();
		}
		int randNum = new Random().nextInt(files.length);
		int randNum1 = new Random().nextInt(tempFiles.length);
		File targetFile = files[randNum];
		File tempImgFile = tempFiles[randNum1];

		// 根据模板裁剪图片
		Map<String, Object> resultMap = VerifyImageUtil.pictureTemplatesCut(tempImgFile,
				targetFile);

		CaptchaCacheBean cacheBean = new CaptchaCacheBean((int) resultMap.get("imageWidth"),
				(int) resultMap.get("xWidth"));
		String sign = RandomUtils.createRandomUUID();
		redisRepository.set(RedissonUtil.getRedisKey(NeptuneConstant.REDIS_CAPTCHA_CACHE, sign),
				cacheBean, neptuneConfig.captchaCacheTime);
		resultMap.put("sign", sign);
		resultMap.remove("imageWidth");
		resultMap.remove("xWidth");
		return resultMap;
	}

	@Override
	public boolean verifyImageCode(LoginRequest loginRequest) {
		if (StringUtils.isBlank(loginRequest.getCanvasLength())
				|| StringUtils.isBlank(loginRequest.getMoveLength())){
			return false;
		}
		try{
			String cacheKey = RedissonUtil.getRedisKey(NeptuneConstant.REDIS_CAPTCHA_CACHE,
					loginRequest.getSign());
			CaptchaCacheBean cacheBean = redisRepository.get(cacheKey, CaptchaCacheBean.class);
			if (cacheBean == null){
				return false;
			}
			redisRepository.remove(cacheKey);
			int initWidth = cacheBean.getImageWidth();
			int initOffset = cacheBean.getOffset();
			int pageWidth = Integer.valueOf(loginRequest.getCanvasLength());
			int pageOffset = Integer.valueOf(loginRequest.getMoveLength());

			DecimalFormat df = new DecimalFormat("0.00000");// 设置保留位数
			double initScale = Double.valueOf(df.format((double) initOffset / initWidth));
			double realScale = Double.valueOf(df.format((double) pageOffset / pageWidth));

			if (realScale * 100 <= (initScale * 100 + neptuneConfig.captchaAcceptableError)
					&& realScale * 100 >= (initScale * 100 - neptuneConfig.captchaAcceptableError)){
				return true;
			}
		} catch (Exception e){
			LOGGER.error("error", e);
		}

		return false;
	}
}
